1 /* 2 Copyright: Marcelo S. N. Mancini, 2018 - 2021 3 License: [https://opensource.org/licenses/MIT|MIT License]. 4 Authors: Marcelo S. N. Mancini 5 6 Copyright Marcelo S. N. Mancini 2018 - 2021. 7 Distributed under the MIT Software License. 8 (See accompanying file LICENSE.txt or copy at 9 https://opensource.org/licenses/MIT) 10 */ 11 12 module hip.event.handlers.keyboard; 13 14 import hip.event.handlers.keyboard_layout; 15 public import hip.event.handlers.button; 16 public import hip.api.input.keyboard; 17 18 import hip.util.data_structures; 19 import hip.error.handler; 20 import hip.util.time, hip.util.array; 21 22 char toUppercase(char a) 23 { 24 ubyte charV = ubyte(a); 25 if(charV >= HipKey.A+32 && charV <= HipKey.Z+32) 26 return cast(char)(charV-32); 27 return a; 28 } 29 30 31 32 33 /** 34 * This class controls callbacks related to keyboard buttons state, as its downtime, uptime, 35 * its current state, modifier key states and callbacks assigned to specific keys. 36 * 37 * Controls what text has been typed in the current frame, useful for Label or Text objects. 38 */ 39 class KeyboardHandler : IHipKeyboard 40 { 41 private __gshared int[256] pressedKeys; 42 private __gshared HipButtonMetadata[256] metadatas; 43 private __gshared string frameText; 44 45 private __gshared bool altPressed; 46 private __gshared bool shiftPressed; 47 private __gshared bool ctrlPressed; 48 private __gshared float keyRepeatDelay = 0.5; 49 50 this() 51 { 52 if(metadatas[0] is null) 53 { 54 for(int i = 0; i < 256; i++) 55 metadatas[i] = new HipButtonMetadata(i); 56 pressedKeys[] = 0; 57 } 58 } 59 60 61 /** 62 * Takes care of the pressed keys array 63 */ 64 private void setPressed(HipKey key, bool press) 65 { 66 ubyte Key = cast(ubyte)key; 67 metadatas[Key].setPressed(press); 68 if(press) 69 { 70 if(pressedKeys.indexOf(Key) == -1) 71 { 72 pressedKeys[pressedKeys.indexOf(0)] = Key; //Assign to null index a key 73 } 74 } 75 else 76 { 77 const int index = pressedKeys.indexOf(0); //Get last index 78 const int upIndex = pressedKeys.indexOf(Key); 79 if(index > 1) 80 { 81 swapAt(pressedKeys, index - 1, upIndex);//Swaps the current key with the last valid key 82 pressedKeys[index - 1] = 0; 83 } 84 else pressedKeys[0] = 0; 85 } 86 switch(key) 87 { 88 case HipKey.ALT: 89 altPressed = press; 90 break; 91 case HipKey.CTRL: 92 ctrlPressed = press; 93 break; 94 case HipKey.SHIFT: 95 shiftPressed = press; 96 break; 97 default: 98 break; 99 } 100 101 } 102 103 void handleKeyUp(HipKey key) 104 { 105 setPressed(key, false); 106 } 107 AHipButtonMetadata getMetadata(char key) const {return metadatas[key];} 108 109 bool isKeyPressed(char key){return metadatas[key]._isPressed;} 110 bool isKeyJustPressed(char key){return metadatas[key].isJustPressed;} 111 bool isKeyJustReleased(char key){return metadatas[key].isJustReleased;} 112 float getKeyDownTime(char key){return metadatas[key].getDownTimeDuration();} 113 float getKeyUpTime(char key){return metadatas[key].getUpTimeDuration();} 114 115 116 /** 117 * Updates the metadata 118 */ 119 void handleKeyDown(HipKey key) 120 { 121 setPressed(key, true); 122 // import hip.console.log; 123 // logln("Set pressed the key ", key); 124 } 125 126 static string getInputText(KeyboardLayout layout) 127 { 128 KeyboardLayout.KeyState state = KeyboardLayout.KeyState.NONE; 129 if(altPressed) 130 state|= KeyboardLayout.KeyState.ALT; 131 if(shiftPressed) 132 state|= KeyboardLayout.KeyState.SHIFT; 133 if(ctrlPressed) 134 state|= KeyboardLayout.KeyState.CTRL; 135 string ret = ""; 136 int i = 0; 137 while(pressedKeys[i] != 0) 138 { 139 const float pressTime = metadatas[pressedKeys[i]].getDownTimeDuration(); 140 if(pressTime >= keyRepeatDelay || metadatas[pressedKeys[i]]._isNewState) 141 ret~= layout.getKey(toUppercase(cast(char)pressedKeys[i]), state); 142 i++; 143 } 144 return ret; 145 } 146 147 void update() 148 { 149 } 150 151 void postUpdate() 152 { 153 for(int i = 0; i < metadatas.length; i++) 154 metadatas[i]._isNewState = false; 155 frameText = ""; 156 } 157 158 }